//! 微服务使用Nacos示例

use nacos_client::{NacosClient, ClientConfig, ServiceInstance};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::time::{sleep, Duration};

/// 微服务注册器
pub struct MicroServiceRegistrar {
    client: Arc<NacosClient>,
    service_name: String,
    instance: ServiceInstance,
}

impl MicroServiceRegistrar {
    pub fn new(
        client: Arc<NacosClient>,
        service_name: impl Into<String>,
        ip: impl Into<String>,
        port: u16,
    ) -> Self {
        let service_name = service_name.into();
        let ip = ip.into();
        
        let mut instance = ServiceInstance::new(
            service_name.clone(),
            "DEFAULT_GROUP".to_string(),
            ip.clone(),
            port,
        );
        instance.metadata = {
            let mut map = HashMap::new();
            map.insert("service".to_string(), service_name.clone());
            map.insert("version".to_string(), "1.0.0".to_string());
            map.insert("protocol".to_string(), "http".to_string());
            map.insert("health_check_path".to_string(), "/health".to_string());
            map
        };

        Self {
            client,
            service_name,
            instance,
        }
    }

    pub async fn register(&self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        let naming_client = self.client.naming_client();
        naming_client.register_instance(&self.service_name, self.instance.clone()).await?;
        
        println!("服务 {} 已注册: {}:{}", 
            self.service_name, self.instance.ip, self.instance.port);
        
        Ok(())
    }

    pub async fn deregister(&self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        let naming_client = self.client.naming_client();
        naming_client.deregister_instance(
            &self.service_name,
            &self.instance.ip,
            self.instance.port
        ).await?;
        
        println!("服务 {} 已注销", self.service_name);
        
        Ok(())
    }
}

/// 微服务发现器
pub struct MicroServiceDiscoverer {
    client: Arc<NacosClient>,
    service_name: String,
}

impl MicroServiceDiscoverer {
    pub fn new(client: Arc<NacosClient>, service_name: impl Into<String>) -> Self {
        Self {
            client,
            service_name: service_name.into(),
        }
    }

    pub async fn discover_instances(
        &self,
        healthy_only: bool,
    ) -> Result<Vec<ServiceInstance>, Box<dyn std::error::Error + Send + Sync>> {
        let naming_client = self.client.naming_client();
        let instances = naming_client.get_instances(&self.service_name, healthy_only
        ).await?;
        
        println!("发现 {} 个 {} 服务实例", instances.len(), self.service_name);
        
        Ok(instances)
    }

    pub async fn get_service_url(&self,
    ) -> Result<Option<String>, Box<dyn std::error::Error + Send + Sync>> {
        let instances = self.discover_instances(true).await?;
        
        if instances.is_empty() {
            return Ok(None);
        }

        // 简单的负载均衡：选择第一个实例
        let instance = &instances[0];
        let url = format!("http://{}:{}", instance.ip, instance.port);
        
        println!("服务 {} 的地址: {}", self.service_name, url);
        
        Ok(Some(url))
    }
}

/// 配置管理器
pub struct ConfigManager {
    client: Arc<NacosClient>,
    namespace: String,
    group: String,
}

impl ConfigManager {
    pub fn new(client: Arc<NacosClient>, namespace: impl Into<String>, group: impl Into<String>) -> Self {
        Self {
            client,
            namespace: namespace.into(),
            group: group.into(),
        }
    }

    pub async fn load_config(&self,
        data_id: &str,
    ) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
        let config_client = self.client.config_client();
        
        let content = config_client.get_config(data_id, &self.group, &self.namespace).await?;
        println!("加载配置 {}:{}, 内容长度: {}", 
            data_id, self.group, content.content.len());
        
        Ok(content.content)
    }

    pub async fn save_config(&self,
        data_id: &str,
        content: &str,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        let config_client = self.client.config_client();
        
        config_client.publish_config(data_id, &self.group, &self.namespace, content).await?;
        println!("保存配置 {}:{}", data_id, self.group);
        
        Ok(())
    }
}

/// 微服务示例：用户服务
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    // 初始化日志
    tracing_subscriber::fmt().init();

    println!("=== 微服务Nacos集成示例 ===\n");

    // 创建Nacos客户端
    let config = ClientConfig::new("127.0.0.1:8848")
        .with_namespace("microservices")
        .with_timeout(3000, 5000);

    let client = Arc::new(NacosClient::new(config).await?);

    // 1. 配置管理
    println!("1. 配置管理:");
    let config_manager = ConfigManager::new(client.clone(), "microservices", "user-service");
    
    // 保存用户服务配置
    let user_service_config = r#"
        server:
          port: 8081
        
        database:
          host: localhost
          port: 3306
          name: user_db
          username: user
          password: user123
          
        redis:
          host: localhost
          port: 6379
          database: 0
          
        logging:
          level: INFO
          file: /var/log/user-service.log
    "#;

    config_manager.save_config("user-service.yml", user_service_config).await?;

    // 加载配置
    let loaded_config = config_manager.load_config("user-service.yml").await?;
    println!("加载的配置长度: {} 字符", loaded_config.len());

    // 2. 服务注册
    println!("\n2. 服务注册:");
    let registrar = MicroServiceRegistrar::new(
        client.clone(),
        "user-service",
        "192.168.1.100",
        8081
    );

    registrar.register().await?;

    // 3. 服务发现
    println!("\n3. 服务发现:");
    let discoverer = MicroServiceDiscoverer::new(client.clone(), "user-service");
    
    if let Some(url) = discoverer.get_service_url().await? {
        println!("发现用户服务地址: {}", url);
    }

    // 4. 订单服务注册（模拟多个服务）
    println!("\n4. 订单服务注册:");
    let order_registrar = MicroServiceRegistrar::new(
        client.clone(),
        "order-service",
        "192.168.1.101",
        8082
    );
    order_registrar.register().await?;

    // 发现订单服务
    let order_discoverer = MicroServiceDiscoverer::new(client.clone(), "order-service");
    if let Some(url) = order_discoverer.get_service_url().await? {
        println!("发现订单服务地址: {}", url);
    }

    // 5. 网关服务发现所有服务
    println!("\n5. 网关服务发现:");
    let services = vec!["user-service", "order-service", "payment-service", "inventory-service"];
    
    for service in services {
        let discoverer = MicroServiceDiscoverer::new(client.clone(), service);
        match discoverer.get_service_url().await {
            Ok(Some(url)) => println!("✓ {}: {}", service, url),
            Ok(None) => println!("✗ {}: 服务未找到", service),
            Err(e) => println!("✗ {}: 错误 - {}", service, e),
        }
    }

    // 6. 健康检查
    println!("\n6. 健康检查:");
    let is_healthy = client.health_check().await?;
    println!("Nacos服务器状态: {}", if is_healthy { "健康" } else { "不健康" });

    // 7. 模拟服务运行
    println!("\n7. 模拟服务运行10秒...");
    
    // 创建监听器来监听服务变更
    #[derive(Debug)]
    struct ServiceWatcher;
    
    #[async_trait::async_trait]
    impl nacos_client::ServiceListener for ServiceWatcher {
        async fn on_service_changed(
            &self,
            service_name: &str,
            instances: &[nacos_client::ServiceInstance],
        ) {
            println!("服务变更: {}, 当前实例数: {}", service_name, instances.len());
        }

        async fn on_instance_added(&self,
            service_name: &str,
            instance: &nacos_client::ServiceInstance,
        ) {
            println!("实例新增: {} - {}:{}", service_name, instance.ip, instance.port);
        }

        async fn on_instance_removed(
            &self,
            service_name: &str,
            instance: &nacos_client::ServiceInstance,
        ) {
            println!("实例删除: {} - {}:{}", service_name, instance.ip, instance.port);
        }
    }

    let watcher = Box::new(ServiceWatcher);
    let naming_client = client.naming_client();
    
    for service in &services {
        naming_client.subscribe_service(service, watcher.clone()).await?;
    }

    // 运行10秒后清理
    sleep(Duration::from_secs(10)).await;

    println!("\n8. 清理资源:");
    
    // 注销服务
    registrar.deregister().await?;
    order_registrar.deregister().await?;

    // 删除配置
    config_manager.save_config("user-service.yml", "").await?;

    // 关闭客户端
    client.close().await;

    println!("\n=== 微服务示例完成 ===");

    Ok(())
}

/// 使用示例：如何创建微服务注册器
#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_microservice_usage() {
        // 这个测试展示了如何使用微服务注册器
        let config = ClientConfig::new("127.0.0.1:8848");
        let client = Arc::new(NacosClient::new(config).await.unwrap());

        let registrar = MicroServiceRegistrar::new(
            client.clone(),
            "test-service",
            "127.0.0.1",
            8080
        );

        // 注册服务
        registrar.register().await.unwrap();

        // 发现服务
        let discoverer = MicroServiceDiscoverer::new(client.clone(), "test-service");
        let instances = discoverer.discover_instances(true).await.unwrap();
        assert!(!instances.is_empty());

        // 清理
        registrar.deregister().await.unwrap();
    }
}